/*
 * Copyright 2008-2009 Daniel Freitas
 * 
 * This file is part of Army Creator.
 * 
 * Army Creator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * Army Creator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with Army Creator. If not, see
 * <http://www.gnu.org/licenses/>.
 */
package com.googlecode.armycreator.datastore.test.unit

import com.googlecode.armycreator.datastore.genericdao.QueryMethodInvocation
import com.googlecode.armycreator.datastore.genericdao.hibernate.HibernateQueryExecutor
import org.hibernate.Query
import org.hibernate.SessionFactory
import org.hibernate.classic.Session
import org.testng.annotations.Test

public class HibernateQueryExecutorUnitTest {

    /*
     * Creates hibernate stubs.
     */
    def queryStub = [
            uniqueResult: { return "" },
            list: { return new ArrayList() },
            getNamedParameters: { return ["param"] as String[] },
            setParameter: {Object[] args -> }] as Query
    def sessionStub = [
            getNamedQuery: { return queryStub }
    ] as Session
    def sessionFactoryStub = { return sessionStub } as SessionFactory

    @Test (groups = ["unit"])
    public void testReturnsListIfInvokedMethodReturnTypeIsList() {
        def queryMethodInvocation = new QueryMethodInvocation(null, null, [param: "param"], List.class)

        HibernateQueryExecutor hibernateQueryExecutor = new HibernateQueryExecutor(sessionFactoryStub)
        def result = hibernateQueryExecutor.executeQueryForMethod(queryMethodInvocation)

        assert result instanceof List
    }

    @Test (groups = ["unit"])
    public void testReturnsObjectIfInvokedMethodDoesNotReturnList() {
        def queryMethodInvocation = new QueryMethodInvocation(null, null, [param: "param"], String.class)

        HibernateQueryExecutor hibernateQueryExecutor = new HibernateQueryExecutor(sessionFactoryStub)
        def result = hibernateQueryExecutor.executeQueryForMethod(queryMethodInvocation)

        assert !(result instanceof List)
    }

    @Test (groups = ["unit"])
    public void testThrowsExceptionIfParameterNameDoesNotExistInQuery() {
        Exception expectedException = null

        def queryMethodInvocation = new QueryMethodInvocation(null, null, [anotherParam: "paramValue"],
                String.class)

        HibernateQueryExecutor hibernateQueryExecutor = new HibernateQueryExecutor(sessionFactoryStub)

        try {
            hibernateQueryExecutor.executeQueryForMethod(queryMethodInvocation)
        } catch (Exception e) {
            expectedException = e;
        }

        assert expectedException != null
        assert expectedException instanceof IllegalArgumentException
    }

    @Test (groups = ["unit"])
    public void testBuildsQueryNameAsClassNamePlusMethodName() {
        def constructedQueryName = "";

        def sessionStub = [
                getNamedQuery: { queryName -> constructedQueryName = queryName; return queryStub }
        ] as Session
        def sessionFactoryStub = { return sessionStub } as SessionFactory

        def queryMethodInvocation = new QueryMethodInvocation("a.b.c.AClass", "aMethod", [param: "param"], String.class)

        HibernateQueryExecutor hibernateQueryExecutor = new HibernateQueryExecutor(sessionFactoryStub)
        hibernateQueryExecutor.executeQueryForMethod(queryMethodInvocation)

        assert constructedQueryName == "a.b.c.AClass.aMethod"
    }
}
